import createDOMElement from './createDOMElement.js'

function moveAryItem(ary, fromIdx, toIdx) {
  const fromItem = ary[fromIdx]

  ary.splice(fromIdx, 1)

  ary.splice(toIdx, 0, fromItem)
}

// 判断两个节点是否相同
function sameVnode(a, b) {
  const akey = a.data && a.data.key
  const bkey = b.data && b.data.key
  return akey === bkey && a.tag === b.tag
}

function isTextNode(vnode) {
  return vnode.tag === undefined
}

export default function patch(oldVnode, newVnode) {
  console.log('-----------', oldVnode, newVnode, '--------')

  let finalVnode = oldVnode

  // 如果newVnode还没有对应的真实的DOM节点，那么就先创建
  if (!newVnode.elm) {
    createDOMElement(newVnode)
  }

  console.log('是否是相同的节点？')
  if (sameVnode(oldVnode, newVnode)) {
    console.log('相同')
    console.log('判断两个节点在内存中是否是同一个对象？')
    if (oldVnode === newVnode) {
      console.log('是，什么都不做')
    } else {
      console.log('不是')
      console.log('看newVnode是否是文本节点？')
      if (isTextNode(newVnode)) {
        console.log('是')
        if (newVnode.text === oldVnode.text) {
          console.log('文本一样，什么都不做')
        } else {
          console.log('文本不一样，更新')
          oldVnode.text = newVnode.text
          // 不要忘了更新真实的DOM节点
          oldVnode.elm.nodeValue = oldVnode.text
        }
      } else {
        console.log('不是，开始diff比对oldVnode.children和newVnode.children')
        finalVnode.children = updateChildren(
          oldVnode.children,
          newVnode.children,
          oldVnode.elm
        )
      }
    }
  } else {
    console.log('不同')
    // oldVnode.elm.parentElement.insertBefore(newVnode.elm, oldVnode.elm)
    oldVnode.elm.before(newVnode.elm)
    oldVnode.elm.remove()
    finalVnode = newVnode
  }
  console.log('-----------end--------')
  return finalVnode
}

function updateChildren(oldChildren, newChildren, parentElm) {
  // 创建旧子节点的副本
  let oldChildrenOfDup = [...oldChildren]

  let oldStartIdx = 0
  let oldStartVnode = oldChildren[oldStartIdx]
  let oldEndIdx = oldChildren.length - 1
  let oldEndVnode = oldChildren[oldEndIdx]

  let newStartIdx = 0
  let newStartVnode = newChildren[newStartIdx]
  let newEndIdx = newChildren.length - 1
  let newEndVnode = newChildren[newEndIdx]

  while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
    if (oldStartVnode === undefined) {
      console.log('oldStartVnode已经被处理过了')
      oldStartVnode = oldChildren[++oldStartIdx]
    } else if (oldEndVnode === undefined) {
      console.log('oldEndVnode已经被处理过了')
      oldEndVnode = oldChildren[--oldEndIdx]
    } else if (sameVnode(oldStartVnode, newStartVnode)) {
      patch(oldStartVnode, newStartVnode)
      oldStartVnode = oldChildren[++oldStartIdx]
      newStartVnode = newChildren[++newStartIdx]
    } else if (sameVnode(oldEndVnode, newEndVnode)) {
      patch(oldEndVnode, newEndVnode)
      oldEndVnode = oldChildren[--oldEndIdx]
      newEndVnode = newChildren[--newEndIdx]
    } else if (sameVnode(oldStartVnode, newEndVnode)) {
      patch(oldStartVnode, newEndVnode)
      // 仅仅更新了真实的DOM节点，没有更新虚拟DOM节点（需要更新，待完成）
      oldEndVnode.elm.after(oldStartVnode.elm)

      moveAryItem(
        oldChildrenOfDup,
        oldChildrenOfDup.findIndex((v) => v === oldStartVnode),
        oldChildrenOfDup.findIndex((v) => v === oldEndVnode)
      )

      oldStartVnode = oldChildren[++oldStartIdx]
      newEndVnode = newChildren[--newEndIdx]
    } else if (sameVnode(oldEndVnode, newStartVnode)) {
      patch(oldEndVnode, newStartVnode)
      oldStartVnode.elm.before(oldEndVnode.elm)

      moveAryItem(
        oldChildrenOfDup,
        oldChildrenOfDup.findIndex((v) => v === oldEndVnode),
        oldChildrenOfDup.findIndex((v) => v === oldStartVnode)
      )

      oldEndVnode = oldChildren[--oldEndIdx]
      newStartVnode = newChildren[++newStartIdx]
    } else {
      console.log('四判断都不成立')
      console.log('看oldChildren中有没有newStartVnode？')
      const oldVnodeIdx = oldChildren.findIndex((oldVnode) =>
        sameVnode(oldVnode, newStartVnode)
      )
      if (oldVnodeIdx === -1) {
        console.log('木有', newStartVnode)
        oldStartVnode.elm.before(newStartVnode.elm)

        oldChildrenOfDup.splice(
          oldChildrenOfDup.findIndex((v) => v === oldStartVnode),
          0,
          newStartVnode
        )

        newStartVnode = newChildren[++newStartIdx]
      } else {
        console.log('有')
        const oldVnode = oldChildren[oldVnodeIdx]
        patch(oldVnode, newStartVnode)
        oldStartVnode.elm.before(oldVnode.elm)

        moveAryItem(
          oldChildrenOfDup,
          oldChildrenOfDup.findIndex((v) => v === oldVnode),
          oldChildrenOfDup.findIndex((v) => v === oldStartVnode)
        )

        oldChildren[oldVnodeIdx] = undefined
        newStartVnode = newChildren[++newStartIdx]
      }
    }
  }

  console.log('循环结束')

  if (oldStartIdx > oldEndIdx && newStartIdx <= newEndIdx) {
    console.log('newChildren中还有新的节点要添加')
    // 这里要把所有剩下的新节点都依次插入到新后的后一个节点前
    const refVnode = newChildren[newEndIdx + 1]
    const refElm = refVnode && refVnode.elm
    for (let i = newStartIdx; i <= newEndIdx; i++) {
      // 如果refElm存在，则将newChild插入到refElm前，如果refElm不存在，则插入到parentElm的所有子节点后
      // parentElm.insertBefore(newChild, refElm)
      parentElm.insertBefore(newChildren[i].elm, refElm)

      if (refVnode) {
        oldChildrenOfDup.splice(
          oldChildrenOfDup.findIndex((v) => v === refVnode),
          0,
          newChildren[i]
        )
      } else {
        oldChildrenOfDup.push(newChildren[i])
      }
    }
  } else if (newStartIdx > newEndIdx && oldStartIdx <= oldEndIdx) {
    console.log('oldChildren中要有节点要删除')
    for (let i = oldStartIdx; i <= oldEndIdx; i++) {
      const oldVnode = oldChildren[i]
      oldVnode && oldVnode.elm.remove()

      oldChildrenOfDup.splice(
        oldChildrenOfDup.findIndex((v) => v === oldVnode),
        1
      )
    }
  }

  return oldChildrenOfDup
}
